/* hal_adc.c */
#include "hal_adc.h"



uint32_t ADC_GetStatusFlags(ADC_Type * base) /* ADC_FLAG_xxxx. */
{
    return base->STS;
}

void ADC_ClearStatusFlags(ADC_Type * base, uint32_t flags) /* ADC_FLAG_xxxx. */
{
    base->STS = flags;
}

void ADC_EnableInterrupts(ADC_Type * base, uint32_t flags) /* ADC_FLAG_xxxx. */
{
    base->INTE |= flags;
}

void ADC_DisableInterrupts(ADC_Type * base, uint32_t flags) /* ADC_FLAG_xxxx. */
{
    base->INTE &= ~flags;
}

void ADC_EnableTemperatureSensor(ADC_Type * base, bool enable)
{
    if (enable)
    {
        base->CTRL |= ADC_CTRL_TSEN_MASK;
    }
    else
    {
        base->CTRL &= ~ADC_CTRL_TSEN_MASK;
    }
}

/* when software raised the request, the hardware would execute the command in the most recent comming time slot and take effect. */
void ADC_RequestConvCmd(ADC_Type * base, ADC_ConvCmd_Type cmd)
{
    base->CTRL |= cmd;
}

void ADC_WaitConvCmd(ADC_Type * base, ADC_ConvCmd_Type cmd)
{
    while (0u == (base->CTRL & cmd))
    {
    }
}

void ADC_InitConv(ADC_Type * base, ADC_ConvInit_Type * init)
{
    uint32_t tmp32 = ((base->CFG0) & ~(  ADC_CFG0_AUTOOFF_MASK
                              | ADC_CFG0_WAIT_MASK
                              | ADC_CFG0_RES_MASK
                              | ADC_CFG0_WM_MASK
                              | ADC_CFG0_DMAEN_MASK
                              | ADC_CFG0_OVRMD_MASK
                             ));

    if (init->EnableAutoOffMode)
    {
        tmp32 |= ADC_CFG0_AUTOOFF_MASK;
    }
    if (init->EnableWaitMode)
    {
        tmp32 |= ADC_CFG0_WAIT_MASK;
    }
    //if (init->TriggerMode == ADC_TriggerMode_Hardware)
    //{
    //    tmp32 |= ADC_CFG0_TRIGMD_MASK;
    //}

    if (init->FifoOverrunMode == ADC_FifoOverrunMode_KeepNewData)
    {
        tmp32 |= ADC_CFG0_OVRMD_MASK;
    }
    
    tmp32 |= ADC_CFG0_RES(init->Resolution)
           | ADC_CFG0_WM(init->FifoWatermark)
           ;

    if (init->EnableDma)
    {
        tmp32 |= ADC_CFG0_DMAEN_MASK;
    }
    
    base->CFG0 = tmp32;
    
    base->CFG1 = ADC_CFG1_PRS(init->ConvClkDiv) | ADC_CFG1_STCNT(init->ConvStartupClkCount);
    base->SMP = ADC_SMP_SMP(init->ConvSamplingClkCount);
}

void ADC_SetConvSeqConf(ADC_Type * base, ADC_ConvSeqConf_Type * conf)
{
    //uint32_t tmp32 = base->CFG0 & ~(ADC_CFG0_SEQLEN_MASK | ADC_CFG0_TRIGMD_MASK | ADC_CFG0_DISCEN_MASK | ADC_CFG0_CONT_MASK);
    uint32_t tmp32 = base->CFG0 & ~(ADC_CFG0_SEQLEN_MASK | ADC_CFG0_TRIGMD_MASK | ADC_CFG0_CONVMD_MASK);

    tmp32 |= ADC_CFG0_SEQLEN(conf->SeqLen-1u) | ADC_CFG0_CONVMD(conf->SeqScanMode);
    
    if (conf->TriggerMode == ADC_TriggerMode_Hardware)
    {
        tmp32 |= ADC_CFG0_TRIGMD_MASK;
    }
    
    base->CFG0 = tmp32;
}

void ADC_SetConvSeqSlot(ADC_Type * base, uint32_t slot, uint32_t channel)
{
    base->CHSEL[slot] = ADC_CHSEL_CHSEL(channel);
}


void ADC_SetConvWatchdogConf(ADC_Type * base, ADC_ConvWatchdogConf_Type * conf)
{
    base->WDCTRL = 0u;
    
    if (conf)
    {
        base->WDTH = ADC_WDTH_THMD(conf->ValidRange)
                   | ADC_WDTH_HIGH(conf->HighLimit)
                   | ADC_WDTH_LOW(conf->LowLimit)
                   ;
        
        /* adc_wdctrl. */
        uint32_t tmp32 = ADC_WDCTRL_WDEN_MASK;
        
        if (conf->ChannelMode == ADC_ConvWatchdogChannelMode_ForOneChannel)
        {
            tmp32 |= ADC_WDCTRL_WDSGL_MASK | ADC_WDCTRL_WDCHSEL(conf->OneChannelIndex);
        }
        base->WDCTRL = tmp32;
    }
}

uint32_t ADC_GetFifoDataRaw(ADC_Type * base)
{
    return base->FIFO;
}

void ADC_GetConvValue(uint32_t fifo_data_raw, uint32_t * channel, uint32_t * val)
{
    *channel = (uint32_t)((fifo_data_raw & ADC_FIFO_CHID_MASK) >> ADC_FIFO_CHID_SHIFT);
    *val = (uint32_t)((fifo_data_raw & ADC_FIFO_DATA_MASK) >> ADC_FIFO_DATA_SHIFT);
}

/* EOF. */

